#include "render_pipeline.h"

render_pipeline * render_pipeline_instance = NULL;

render_pipeline * render_pipeline::self(){
	if (!render_pipeline_instance)
		render_pipeline_instance = new render_pipeline;
	return render_pipeline_instance;
}

render_pipeline::render_pipeline(){
	if (load_settings()!=0){
		SCREEN_WIDTH=640;
		SCREEN_HEIGHT=480;
		SCREEN_BPP=32;
		FRAMES_PER_SECOND=60;
		FULLSCREEN=0;
		C_FPS=1;
		
		save_settings();
	}
	if (init()!=true){
		debug("Init Failed!!!");
	}
	
	_reset_cam();
	cam_spd=3;
	
	fps_reg.start();
		
}

int render_pipeline::load_settings(){
	FILE *screen_config = fopen("./config_screen","r");
	if (screen_config==NULL)
		return -1;
	if (fscanf(screen_config,"%d",&SCREEN_WIDTH)==EOF)
		return -1;
	if (fscanf(screen_config,"%d",&SCREEN_HEIGHT)==EOF)
		return -1;
	if (fscanf(screen_config,"%d",&SCREEN_BPP)==EOF)
		return -1;
	if (fscanf(screen_config,"%d",&FRAMES_PER_SECOND)==EOF)
		return -1;
	if (fscanf(screen_config,"%d",&FULLSCREEN)==EOF)
		return -1;
	if (fscanf(screen_config,"%d",&C_FPS)==EOF)
		return -1;
	return 0;
}

int render_pipeline::save_settings(){
	FILE *screen_config = fopen("./config_screen","w");
	if (screen_config==NULL)
		return -1;
	fprintf(screen_config,"%d\n",SCREEN_WIDTH);
	fprintf(screen_config,"%d\n",SCREEN_HEIGHT);
	fprintf(screen_config,"%d\n",SCREEN_BPP);
	fprintf(screen_config,"%d\n",FRAMES_PER_SECOND);
	fprintf(screen_config,"%d\n",FULLSCREEN);
	fprintf(screen_config,"%d\n",C_FPS);

	return 0;
}

void render_pipeline::_draw(obj * object){
	if (object->to_draw!=1)
		return;
	if (object->transparent==1){
		glEnable(GL_BLEND);
//		glDisable(GL_DEPTH_TEST);
	}
	if (object->loaded!=1){
		debug("Trying to draw wrong object");
		return;
	}
	
	glPushMatrix();
		glTranslatef(object->x,object->y,object->z);
		glRotatef(57.2957795130823208768*object->rot,0,0,1);
		glBindTexture( GL_TEXTURE_2D, object->texture );
		glBegin(GL_TRIANGLES);
			for (int i=0;i<object->faces.size();i++)
				for (int j=0;j<3;j++){
//					debug("%f %f\n",object->UVs[object->faces[i][j+3]][0],object->UVs[object->faces[i][j+3]][1]);
					glTexCoord2f(object->UVs[object->faces[i][j+3]][0],1-object->UVs[object->faces[i][j+3]][1]);
//					debug("%f %f %f\n",object->verts[object->faces[i][j]][0],object->verts[object->faces[i][j]][1],object->verts[object->faces[i][j]][2]);
					glVertex3f(object->verts[object->faces[i][j]][0],object->verts[object->faces[i][j]][1],object->verts[object->faces[i][j]][2]);
				}
		glEnd();
	glPopMatrix();
		
	if (object->transparent==1){
		glDisable(GL_BLEND);
//		glEnable(GL_DEPTH_TEST);
	}
}


void render_pipeline::_draw_scene(){
	if (C_FPS==1 && fps_reg.get_ticks() < 1000 / FRAMES_PER_SECOND){
		SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps_reg.get_ticks() );
	}
	else{
		debug("%s: %d: Nestiham o %d ms\n",__FILE__,__LINE__, fps_reg.get_ticks()-( 1000 / FRAMES_PER_SECOND ));
	}
	last_frame_lenght=fps_reg.get_ticks();
	fps_reg.start();
	SDL_GL_SwapBuffers();
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
//	gluLookAt(	)
	glRotatef(-180/M_PI*cam_rot+90,0,0,1);
	glTranslatef(-cam_x,-cam_y,0);
}

void render_pipeline::_update_cam(float _cam_x,float _cam_y,float _cam_rot){
	cam_x= (1-cam_spd*time_elapsed())*cam_x+cam_spd*time_elapsed()*_cam_x;
	cam_y= (1-cam_spd*time_elapsed())*cam_y+cam_spd*time_elapsed()*_cam_y;
	cam_rot=_cam_rot;
	
	if (abs(cam_rot-_cam_rot)>M_PI)	//atan2 mohol preskocit!!!
		if (cam_rot<_cam_rot)
			cam_rot= (1-cam_spd*time_elapsed())*cam_rot+cam_spd*time_elapsed()*(_cam_rot-2*M_PI);
		else
			cam_rot= (1-cam_spd*time_elapsed())*cam_rot+cam_spd*time_elapsed()*(_cam_rot+2*M_PI);
	else
		cam_rot= (1-cam_spd*time_elapsed())*cam_rot+cam_spd*time_elapsed()*_cam_rot;
	
	while (cam_rot<0){
		cam_rot+=2*M_PI;
		debug("1cam_rot %f\n",cam_rot);
	}
	while (cam_rot>2*M_PI){
		cam_rot-=2*M_PI;
		debug("2cam_rot %f\n",cam_rot);
	}

}

bool render_pipeline::createWindow (){
	int flag = SDL_OPENGL;
	if (FULLSCREEN==1)
		flag |=SDL_FULLSCREEN;
	if( SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, flag ) == NULL )
	{
		debug("SDL_SetVideoMode error");
		return false;
	}
}

bool render_pipeline::init_GL(){
	//Set clear color
	glClearColor( 0, 0, 0, 0 );

	//Set projection
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	obzor=20;
	glOrtho( -obzor, obzor, -obzor, obzor, -obzor, 1 );

	//Initialize modelview matrix
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();

	glClearDepth(1.0f);
	glDepthFunc(GL_LESS);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_NORMALIZE);
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//If there was any errors
	if( glGetError() != GL_NO_ERROR )
	{
		debug("Error in init_GL");
		return false;
	}

	//If everything initialized
	return true;
}

bool render_pipeline::init()
{
	//Initialize SDL
	if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
	{
		debug("SDL_Init error");
		return false;
	}

	createWindow();

	//Initialize OpenGL
	if( init_GL() == false )
	{
		debug("Error in init_GL");
		return false;
	}

	//Set caption
	SDL_WM_SetCaption( "Bugy game", NULL );
	return true;
}
